<?php
/**
 * PHP生成树形结构
 * Created by PhpStorm.
 * User: jaylen
 * Date: 2020-05-03
 * Time: 21:35
 */

namespace service;


class TreeService
{
    /**
     * 返回elementTable的树形结构数据
     * @param $data 原始数据
     * @return array
     */
    public static function elementTableTree($data)
    {
        if (empty($data) || !is_array($data)) {
            return [];
        }

        $tree_data = self::listToTree($data,'id','pid','children');

        return empty($tree_data) ? $data : $tree_data;
    }

    /**
     * 返回elementTree的树形结构数据
     * @param $data 原始数据
     * @param array $select 默认被选中的节点
     * @param string $id id字段
     * @param string $pid pid字段
     * @param string $name 标题字段
     * @param string $children 下级字段
     * @param int $root 顶级的pid编号
     * @return array
     */
    public static function elementTree($data, $select = [], $id = 'id', $pid = 'pid', $name = 'title', $children = 'children', $root = 0)
    {
        if (empty($data) || !is_array($data)) {
            return [
                'select' => [],
                'tree' => []
            ];
        }

        $list_tree = self::listToTree($data, $id, $pid, $children, $root);

        // 生成elementTree
        $element_tree = self::_formatElementTree($list_tree, $select, $name, $id, $children);

        return [
            'select' => $select,
            'tree' => $element_tree
        ];
    }

    /**
     * 获取elementOptionsGroup的数据
     * @param $data
     * @param string $id
     * @param string $pid
     * @param string $children
     * @param int $root
     * @return array
     */
    public static function elementOptionsGroup($data, $id = 'id', $pid = 'pid', $children = 'children', $root = 0)
    {
        if (empty($data) || !is_array($data)) {
            return [];
        }

        $list_tree = self::listToTree($data, $id, $pid, $children, $root);

        return empty($list_tree) ? $data : $list_tree;
    }

    /**
     * 把返回的数据集转换成Tree
     * @param $list 待转换的数据
     * @param string $pk 主键id
     * @param string $pid 上级id
     * @param string $child 存放子数据数组的key名
     * @param int $root 顶级的pid编号
     * @return array
     */
    public static function listToTree($list, $pk = 'id', $pid = 'pid', $child = '_child', $root = 0){

        //创建Tree
        $tree = [];
        if (is_array($list)){
            //创建基于主键的数组索引
            $refer = array();
            foreach ($list as $key => $data) {
                $refer[$data[$pk]] =& $list[$key];
            }

            foreach ($list as $key => $data) {
                //判断是否存在parent
                $parentId = $data[$pid];
                if ($root == $parentId){    //如果是顶级
                    $tree[] =& $list[$key];
                }else{  //存在父级
                    if (isset($refer[$parentId])){  //判断父级数据是否存在
                        $parent =& $refer[$parentId];
                        $parent['childs_id'][] = $data[$pk];   //为父级数据添加对应的子id
                        $parent[$child][] =& $list[$key];   //添加子的数据
                    }
                }
            }
        }

        return $tree;
    }

    /**
     * 返回对应id下所有子元素的id
     * @param $data 需要查看的原始数据
     * @param $id id
     * @param string $pk id的字段名
     * @param string $pid pid的字段名
     * @param bool $clear 是否清空数组
     * @return array
     */
    public static function getChildrenPid($data, $id, $pk = 'id', $pid = 'pid', $clear = false) {

        static $pids = [];

        if ($clear){
            $pids = [];
        }

        foreach ($data as $key => $item) {
            if ($item[$pid] == $id){
                $pids[] = $item[$pk];
                unset($data[$key]);
                self::getChildrenPid($data,$item[$pk],$pk,$pid);
            }
        }

        return $pids;
    }

    /**
     * 格式化elementTree的数据
     * @param $data 进行tree结构后的数据
     * @param array $select 默认选中的节点
     * @param string $name 标题字段
     * @param string $id id字段
     * @param string $children 下级字段
     * @return array
     */
    public static function _formatElementTree($data, $select = [], $name = 'title', $id = 'id', $children = 'children')
    {
        $element_tree = [];

        // 往数组中添加数据
        foreach ($data as $key => $value) {
            $element_tree[$key]['id'] = $value[$id];
            $element_tree[$key]['label'] = $value[$name];
            if (in_array($value[$id],$select) && !isset($value[$children])) {
                $element_tree[$key]['disabled'] = true; // 默认选中的不允许点击
            }
            if (isset($value[$children])) {
                $element_tree[$key]['children'] = self::_formatElementTree($value[$children], $select, $name, $id, $children);
            } else {
                $element_tree[$key]['end_node'] = true; // 如果已经没有子元素，则标记当前元素是最后一个元素
            }

            unset($data[$key]);
        }

        return $element_tree;
    }
}